//
// file : inet_tmr.h
// date : 09/09/07
//
// there are two ways to drive a user-layer timer: 
//  (1) a constant ticking
//  (2) delta firing
// for (1) the master timer is awaked every tick period to check for
// expired user timers and call their timer subroutines
// for (2) the master timer is reset every time a user timer expires to the
// interval the next timer would expire. 
// timer context blocks are orgnized incrementally as a list. 
// timer context blocks are allocated by timer manager and recycled without
// user intervine.
// 
#ifndef INET_TMR_H_
#define INET_TMR_H_

#ifdef __cplusplus
extern "C" {
#endif

#ifndef TMR_DEFAULT_BEAT
    // default heart beat in milliseconds
    #define TMR_DEFAULT_BEAT  (100)
#endif

struct utimer_t;

//
// timer routine prototype
//
typedef void (__stdcall * f_timeup)(struct utimer_t *tb);

typedef struct utimer_t
{
#define UT_FREE_TB     (1)
#define UT_MIN_DELAY   (2)

    unsigned long ut_flags;
    unsigned long ut_ticks;    // system ticks count to fire
    long          ut_delay;    // initial delay in milliseconds
    long          ut_cycle;    // repeat interval in milliseconds
    void*         ut_param[4]; // void* parameters
    f_timeup      ut_awake;

}  utimer_t; 

//
// timer list node
//
typedef struct utnode_t
{
    struct utnode_t *next_;       // to next
    long             cycle;       // copy from timer.ut_cycle
    long             delay;       // delay in milliseconds to fire
    unsigned long    ticks;       // ticks in milliseconds to fire
    utimer_t         timer;       // what user sees

}  utnode_t;

//
// master timer context
//
typedef struct uthead_t
{
    void            *owner;      // pointer to owner
    utnode_t        *alist;      // in-use nodes list
    utnode_t        *blist;      // head of free nodes list
    long             beat_;      // milliseconds per heart beat
    long             count;      // number of blocks in array
    utnode_t         array[1];   // array of blocks

}  uthead_t;



void*     __stdcall tmr_alloca_(void *mem, size_t *size, long count);
utnode_t* __stdcall tmr_getnode(void *thead);
void      __stdcall tmr_putnode(void *thead, utnode_t *tnode);
void      __stdcall tmr_signals(void *thead);
void*     __stdcall tmr_setownr(void *thead, void *domain);
long      __stdcall tmr_insert_(void *thead, utimer_t *tmrctx);
long      __stdcall tmr_beating(void *thead, long ms_beat);
long      __stdcall tmr_stopall(void *thead );

//
// platform specific
//
#ifndef tick_count   // for windows, it is defined in inet_win.h
    unsigned long  __stdcall tick_count(void);
#endif

long      __stdcall tmr_trigger(void *thead, long ms_due);

#ifdef __cplusplus
}
#endif


///////////////////////////////////////////////////////////////////////////////
#endif // INET_TMR_H_
